﻿using System;
using System.Windows;
using System.Windows.Media;

namespace Brjnk.GpxExplorer.Workspace.BitmapExport
{
    public class ArrowBackgroundBuilder
    {
        private ArrowLabel label;

        public ArrowBackgroundBuilder(ArrowLabel label)
        {
            this.label = label;
        }

        public System.Windows.Media.DrawingBrush GetResult()
        {
            var path = CreatePath();
            var drawing = new GeometryDrawing();
            drawing.Brush = label.Style.BackgroundBrush;
            drawing.Pen = new Pen(label.Style.BorderBrush, label.Style.BorderThickness);
            drawing.Pen.EndLineCap = PenLineCap.Triangle;
            drawing.Pen.StartLineCap = PenLineCap.Triangle;
            drawing.Geometry = path;
            return new DrawingBrush(drawing);
        }

        private PathGeometry CreatePath()
        {
            var path = new PathGeometry();
            var figure = new PathFigure();
            figure.IsClosed = false; //při nastavení na true se chová podivně. Bezdůvodně mění šířku výsledné grafiky při změně tloušťky šipky (při nenulové tloušťce pera)

            switch (label.ArrowStyle.ArrowType)
            {
                case ArrowType.None:
                    CreateNoneArrow(figure);
                    break;

                case ArrowType.LeftArrow:
                    CreateLeftArrow(figure);
                    break;

                case ArrowType.LeftUpArrow:
                    CreateLeftUpArrow(figure);
                    break;

                case ArrowType.LeftDownArrow:
                    CreateLeftDownArrow(figure);
                    break;

                case ArrowType.RightArrow:
                    CreateRightArrow(figure);
                    break;

                case ArrowType.RightUpArrow:
                    CreateRightUpArrow(figure);
                    break;

                case ArrowType.RightDownArrow:
                    CreateRightDownArrow(figure);
                    break;

                case ArrowType.UpArrow:
                    CreateUpArrow(figure);
                    break;

                case ArrowType.DownArrow:
                    CreateDownArrow(figure);
                    break;

                default:
                    throw new ArgumentOutOfRangeException("ArrowType");
            }

            //var tmpFig = new PathFigure();
            //tmpFig.StartPoint = new Point(0, 247);
            //tmpFig.Segments.Add(new LineSegment(new Point(182, 247.29),true));
            //tmpFig.Segments.Add(new LineSegment(new Point(182, 200), true));
            //tmpFig.Segments.Add(new LineSegment(new Point(314, 200), true));
            //tmpFig.Segments.Add(new LineSegment(new Point(314, 295), true));
            //tmpFig.Segments.Add(new LineSegment(new Point(182, 294), true));
            //tmpFig.Segments.Add(new LineSegment(new Point(182, 247), true));
            //tmpFig.IsClosed = false;
            path.Figures.Add(figure);
            //path.Figures.Add (tmpFig);
            path.Freeze();
            return path;
        }

        private void CreateRightDownArrow(PathFigure figure)
        {
            double thickness = label.ArrowStyle.ArrowThickness * (1.0 / Math.Sqrt(2.0));
            thickness = Math.Min(label.ContentHeight, thickness);
            thickness = Math.Min(label.ContentWidth, thickness);
            figure.StartPoint = new Point(label.Width, label.Height);
            AddPoint(figure,
                label.Width - label.ContentMargin.Right - thickness,
                label.Height - label.ContentMargin.Bottom);
            AddPoint(figure,
                0,
                label.Height - label.ContentMargin.Bottom);
            AddPoint(figure,
                0,
                0);
            AddPoint(figure,
                label.Width - label.ContentMargin.Right,
                0);
            AddPoint(figure,
                label.Width - label.ContentMargin.Right,
                label.Height - label.ContentMargin.Bottom - thickness);
            AddPoint(figure, label.Width, label.Height);
        }

        private void CreateRightUpArrow(PathFigure figure)
        {
            double thickness = label.ArrowStyle.ArrowThickness * (1.0 / Math.Sqrt(2.0));
            thickness = Math.Min(label.ContentHeight, thickness);
            thickness = Math.Min(label.ContentWidth, thickness);
            figure.StartPoint = new Point(label.Width, 0);
            AddPoint(figure,
                label.Width - label.ContentMargin.Right,
                label.ContentMargin.Top + thickness);
            AddPoint(figure,
                label.Width - label.ContentMargin.Right,
                label.Height);
            AddPoint(figure,
                0,
                label.Height);
            AddPoint(figure,
                0,
                label.ContentMargin.Top);
            AddPoint(figure,
                label.Width - label.ContentMargin.Right - thickness,
                label.ContentMargin.Top);
            AddPoint(figure, label.Width, 0);
        }

        private void CreateLeftDownArrow(PathFigure figure)
        {
            double thickness = label.ArrowStyle.ArrowThickness * (1.0 / Math.Sqrt(2.0));
            thickness = Math.Min(label.ContentHeight, thickness);
            thickness = Math.Min(label.ContentWidth, thickness);
            figure.StartPoint = new Point(0, label.Height);
            AddPoint(figure,
                label.ContentMargin.Left,
                label.Height - label.ContentMargin.Bottom - thickness);
            AddPoint(figure,
                label.ContentMargin.Left,
                0);
            AddPoint(figure,
                label.Width,
                0);
            AddPoint(figure,
                label.Width,
                label.Height - label.ContentMargin.Bottom);
            AddPoint(figure,
                label.ContentMargin.Left + thickness,
                label.Height - label.ContentMargin.Bottom);
            AddPoint(figure, 0, label.Height);
        }

        private void CreateLeftUpArrow(PathFigure figure)
        {
            double thickness = label.ArrowStyle.ArrowThickness * (1.0 / Math.Sqrt(2.0));
            thickness = Math.Min(label.ContentHeight, thickness);
            thickness = Math.Min(label.ContentWidth, thickness);
            figure.StartPoint = new Point(0, 0);
            AddPoint(figure,
                label.ContentMargin.Left + thickness,
                label.ContentMargin.Top);
            AddPoint(figure,
                label.Width,
                label.ContentMargin.Top);
            AddPoint(figure,
                label.Width,
                label.Height);
            AddPoint(figure,
                label.ContentMargin.Left,
                label.Height);
            AddPoint(figure,
                label.ContentMargin.Left,
                label.ContentMargin.Top + thickness);
            AddPoint(figure, 0, 0);
        }

        private void CreateLeftArrow(PathFigure figure)
        {
            double center = label.Height / 2;
            double thicknessHalf = Math.Min(label.ArrowStyle.ArrowThickness, label.ContentHeight) / 2.0;
            figure.StartPoint = new Point(0, center);
            AddPoint(figure, label.ContentMargin.Left, center - thicknessHalf);
            AddPoint(figure, label.ContentMargin.Left, 0);
            AddPoint(figure, label.Width, 0);
            AddPoint(figure, label.Width, label.Height);
            AddPoint(figure, label.ContentMargin.Left, label.Height);
            AddPoint(figure, label.ContentMargin.Left, center + thicknessHalf);
            AddPoint(figure, 0, center);
        }

        private void CreateRightArrow(PathFigure figure)
        {
            double center = label.Height / 2;
            double thicknessHalf = Math.Min(label.ArrowStyle.ArrowThickness, label.ContentHeight) / 2.0;
            figure.StartPoint = new Point(label.Width, center);
            AddPoint(figure, label.Width - label.ContentMargin.Right, center + thicknessHalf);
            AddPoint(figure, label.Width - label.ContentMargin.Right, label.Height);
            AddPoint(figure, 0, label.Height);
            AddPoint(figure, 0, 0);
            AddPoint(figure, label.Width - label.ContentMargin.Right, 0);
            AddPoint(figure, label.Width - label.ContentMargin.Right, center - thicknessHalf);
            AddPoint(figure, label.Width, center);
        }

        private void CreateUpArrow(PathFigure figure)
        {
            double center = label.Width / 2.0;
            double thicknessHalf = Math.Min(label.ArrowStyle.ArrowThickness, label.ContentWidth) / 2.0;
            figure.StartPoint = new Point(center, 0);
            AddPoint(figure, center + thicknessHalf, label.ContentMargin.Top);
            AddPoint(figure, label.Width, label.ContentMargin.Top);
            AddPoint(figure, label.Width, label.Height);
            AddPoint(figure, 0.0, label.Height);
            AddPoint(figure, 0, label.ContentMargin.Top);
            AddPoint(figure, center - thicknessHalf, label.ContentMargin.Top);
            AddPoint(figure, center, 0);
        }

        private void CreateDownArrow(PathFigure figure)
        {
            double center = label.Width / 2.0;
            double thicknessHalf = Math.Min(label.ArrowStyle.ArrowThickness, label.ContentHeight) / 2.0;
            figure.StartPoint = new Point(center, label.Height);
            AddPoint(figure, center - thicknessHalf, label.Height - label.ContentMargin.Bottom);
            AddPoint(figure, 0, label.Height - label.ContentMargin.Bottom);
            AddPoint(figure, 0, 0);
            AddPoint(figure, label.Width, 0);
            AddPoint(figure, label.Width, label.Height - label.ContentMargin.Bottom);
            AddPoint(figure, center + thicknessHalf, label.Height - label.ContentMargin.Bottom);
            AddPoint(figure, center, label.Height);
        }

        private void CreateNoneArrow(PathFigure figure)
        {
            figure.StartPoint = new Point(0, 0);
            figure.Segments.Add(new LineSegment(new Point(label.Width, 0), true));
            figure.Segments.Add(new LineSegment(new Point(label.Width, label.Height), true));
            figure.Segments.Add(new LineSegment(new Point(0, label.Height), true));
            figure.Segments.Add(new LineSegment(new Point(0, 0), true));
        }

        private void AddPoint(PathFigure figure, double x, double y)
        {
            figure.Segments.Add(new LineSegment(new Point(x, y), true));
        }
    }
}